﻿using GN.Pay.Client.Response;
using GN.Pay.Client.Utils;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using Newtonsoft.Json.Serialization;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace GN.Pay.Client.Manager
{
    /// <summary>
    /// 服务请求管理
    /// </summary>
    class ServiceRequestManager : ServiceManager
    {
        private readonly string requestUrl;

        /// <summary>
        /// 实例化 ServiceRequestManager 新实例
        /// </summary>
        /// <param name="client">客户端</param>
        public ServiceRequestManager(IServiceClient client) : base(client)
        {
            this.requestUrl = this.GetFullUrl(client.PayConfigure.ServerUrl, client.GatewayPath);

        }

        private string GetFullUrl(string url, string path)
        {
            url = url.Trim();
            path = path.Trim();
            if (!url.EndsWith("/"))
            {
                url = url + "/";
            }
            if (path.Length > 1 && path.StartsWith("/"))
            {
                path = path.Substring(1, path.Length - 1);
            }
            return url + path;
        }

        /// <summary>
        /// 请求字典
        /// </summary>
        /// <typeparam name="TRequest">请求类型</typeparam>
        /// <param name="serviceName">服务名称</param>
        /// <param name="request">请求</param>
        /// <returns></returns>
        private IDictionary<string, string> RequestDictionary<TRequest>(string serviceName
            , TRequest request)
            where TRequest : class
        {
            var signDic = new SignDictionary();
            signDic["service"] = serviceName;
            signDic["appId"] = this.Client.PayConfigure.AppId;
            signDic["merchantId"] = this.Client.PayConfigure.MerchantId;
            signDic["randomStr"] = Guid.NewGuid().ToString("N");
            signDic["timeStamp"] = DateTimeUtils.CurrentUtcTimeStampMilliseconds.ToString();
            if (request != null)
            {
                if (request is string)
                {
                    signDic["params"] = request.ToString();
                }
                else
                {
                    signDic["params"] = JsonConvert.SerializeObject(request, this.JsonSerializerSettings);
                }
            }
            string content = signDic.UrlLinkString() + "&key=" + this.Client.PayConfigure.AppKey;
            signDic["sign"] = Md5Utils.Sgin(content, Encoding.UTF8);
            return signDic;
        }

        /// <summary>
        /// 请求结果
        /// </summary>
        /// <typeparam name="TRequest"></typeparam>
        /// <param name="serviceName"></param>
        /// <param name="request"></param>
        /// <returns></returns>
        private string RequestResultString<TRequest>(string serviceName, TRequest request) where TRequest : class
        {
            ExceptionUtils.CheckNotNullOrNotWhiteSpace(serviceName, nameof(serviceName));
            ValidationManager.Validate(request);
            var requestDictionary = this.RequestDictionary(serviceName, request);
            var resultString = HttpUtils.PostString(this.requestUrl, requestDictionary, this.Client.Encoding);
            if (string.IsNullOrWhiteSpace(resultString))
            {
                ExceptionUtils.ThrowJsonFormatException(resultString);
            }
            else
            {
                resultString = resultString.Trim();
                if (resultString[0] != '{' || resultString[resultString.Length - 1] != '}')
                {
                    ExceptionUtils.ThrowJsonFormatException(resultString);
                }
            }
            return resultString;
        }

        /// <summary>
        /// 命令请求
        /// </summary>
        /// <param name="serviceName">服务名称</param>
        /// <param name="jsonParams">Json请求</param>
        /// <returns></returns>
        public JToken CommandRequest(string serviceName, string jsonParams)
        {
            if (!string.IsNullOrWhiteSpace(jsonParams))
            {
                jsonParams = jsonParams.Trim();
                if (jsonParams[0] != '{' || jsonParams[jsonParams.Length - 1] != '}')
                {
                    ExceptionUtils.ThrowJsonFormatException(jsonParams);
                }
            }
            var resultString = this.RequestResultString(serviceName, jsonParams);
            var res = JsonConvert.DeserializeObject<PayJsonResponse>(resultString);
            res.ErrorCheck();
            res.SginVerify(this.Client.PayConfigure.AppKey, resultString);
            return res.Result();
        }

        /// <summary>
        /// 服务请求
        /// </summary>
        /// <typeparam name="TRequest">请求类型</typeparam>
        /// <typeparam name="TResult">响应类型</typeparam>
        /// <param name="serviceName">服务名称</param>
        /// <param name="request">请求</param>
        /// <returns></returns>
        public TResult ServiceRequest<TRequest, TResult>(string serviceName, TRequest request)
            where TRequest : class
        {
            var resultString = RequestResultString(serviceName, request);
            var res = JsonConvert.DeserializeObject<PayJsonResponse>(resultString);
            res.ErrorCheck();
            res.SginVerify(this.Client.PayConfigure.AppKey, resultString);
            return res.ToResult<TResult>();
        }

        /// <summary>
        /// 服务请求
        /// </summary>
        /// <typeparam name="TRequest">请求类型</typeparam>
        /// <param name="serviceName">服务名称</param>
        /// <param name="request">请求</param>
        /// <returns></returns>
        public void ServiceRequest<TRequest>(string serviceName, TRequest request)
            where TRequest : class
        {
            var resultString = this.RequestResultString(serviceName, request);
            var res = JsonConvert.DeserializeObject<PayJsonResponse>(resultString);
            res.ErrorCheck();
            res.SginVerify(Client.PayConfigure.AppKey, resultString);
        }
    }
}
